package cn.crystalorigin.plugin.managers

import cn.crystalorigin.plugin.AsyncLoader
import cn.crystalorigin.plugin.Core
import cn.crystalorigin.plugin.event.TickEventRunner
import cn.crystalorigin.plugin.util.MSTimer
import cn.crystalorigin.plugin.util.TimeUnit
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps
import org.bukkit.Bukkit
import org.bukkit.entity.EnderCrystal
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.vehicle.VehicleUpdateEvent

object CombatManager : AsyncLoader(), Listener {
    override val name = "CombatManager"
    private val playerBreakCrystalMap = Object2ObjectMaps.synchronize(Object2ObjectLinkedOpenHashMap<Player, MSTimer>())
    private val doCrystalSpeedLimit by Core.INSTANCE.toCache { getConfigBoolean("crystals.speedLimit") }
    private val crystalSpeedLimitTimeUnit by Core.INSTANCE.toCache {
        when (getConfigString("crystals.speedLimitTimeUnit")) {
            "MILLISECOND" -> TimeUnit.MILLISECOND
            "SECOND" -> TimeUnit.SECOND
            "MINUTE" -> TimeUnit.MINUTE
            "HOUR" -> TimeUnit.HOUR
            else -> throw IllegalArgumentException()
        }
    }
    private val crystalSpeedLimitDelay by Core.INSTANCE.toCache { getConfigInt("crystals.speedLimitDelay") }

    override suspend fun load() {
        Bukkit.getPluginManager().registerEvents(this, Core.INSTANCE)
        TickEventRunner.onTickSuspend {
            Bukkit.getOnlinePlayers().forEach {
                if (playerBreakCrystalMap[it] == null) playerBreakCrystalMap[it] = MSTimer()
            }
        }
    }

    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) {
        if (doCrystalSpeedLimit) {
            if (event.damager is Player && event.entity is EnderCrystal) {
                if (playerBreakCrystalMap[event.damager]?.checkAndReset(crystalSpeedLimitDelay, crystalSpeedLimitTimeUnit) != true)
                    event.isCancelled = true
                // todo
            }
        }
    }
}